﻿using KqAutoDesign.Base;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Net.Mime.MediaTypeNames;

namespace KqAutoDesign.Models
{
    /// <summary>
    /// 模块的基类，
    /// </summary>
    public class ModuleBase:IClone<ModuleBase>,INotifyPropertyChanged, IGetGlobalParams
    {
        public ModuleBase() { }

        public event PropertyChangedEventHandler PropertyChanged;
        public void RaisePropertyChanged(string propName)
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propName));
            }
        }
        private int _id;

        public int Id
        {
            get { return _id; }
            set
            {
                if (_id != value)
                {
                    _id = value;
                    RaisePropertyChanged(nameof(Id));
                }
            }
        }

        private string _name;
        public string Name 
        {
            get { return _name; }
            set
            {
                if (_name != value)
                {
                    _name = value;
                    RaisePropertyChanged(nameof(Name));
                }
            }
        }
        private string _description;
        public string Description
        {
            get { return _description; }
            set
            {
                if (_description != value)
                {
                    _description = value;
                    RaisePropertyChanged(nameof(Description));
                }
            }
        }
        private RegistedApp _app;
        public RegistedApp App
        {
            get { return _app; }
            set
            {
                if (_app != value)
                {
                    _app = value;
                    Icon = _app?.Icon;
                    RaisePropertyChanged(nameof(App));
                }
            }
        }

        private string _icon;
        /// <summary>
        /// 图标
        /// </summary>
        public string Icon
        {
            get { return _icon; }
            set
            {
                if(_icon != value)
                {
                    _icon = value;
                    RaisePropertyChanged(nameof(Icon));
                }
            }
        }

        private Script _bScript;
        /// <summary>
        /// 运行脚本文件
        /// </summary>
        public Script BatchScript
        {
            get { return _bScript; }
            set
            {
                if(value != _bScript)
                {
                    _bScript = value;
                    RaisePropertyChanged(nameof(Script));
                }
            }
        }

        private ObservableCollection<Script> _fScripts;
        /// <summary>
        /// 功能脚本文件路径
        /// </summary>
        public ObservableCollection<Script> FunctionScripts
        {
            get { return _fScripts; }
            set
            {
                if (value != _fScripts)
                {
                    _fScripts = value;
                    RaisePropertyChanged(nameof(FunctionScripts));
                }
            }
        }

        public bool CanRun = false;
        /// <summary>
        /// 生成脚本文件
        /// </summary>
        public void MakeScriptFiles() 
        {
            BatchScript.MakeScriptFile();
            foreach (var fs in FunctionScripts)
            {
                fs.MakeScriptFile();
            }
            CanRun = true;
        }
        /// <summary>
        /// 运行脚本文件
        /// </summary>
        public void Run()
        {
            Process process = new Process();
            process.StartInfo.WorkingDirectory = BatchScript.WorkDir;
            process.StartInfo.UseShellExecute = false;
            process.StartInfo.FileName = BatchScript.WorkDir+BatchScript.FileName;
            process.Start();
            process.WaitForExit();
        }

        /// <summary>
        /// 从功能脚本中获取所有参数
        /// </summary>
        public virtual void GetAllParamsFromScript() { }
        /// <summary>
        /// 将所有参数设置到功能脚本中
        /// </summary>
        public virtual void SetParamsToScript() { }

        public ModuleBase Clone()
        {
            var cloned =MemberwiseClone() as ModuleBase;
            cloned.BatchScript = BatchScript?.Clone();
            cloned.FunctionScripts = new ObservableCollection<Script>(FunctionScripts);
            return cloned;
        }

        public List<GroupScriptParam> GetGlobalParams()
        {
            List<GroupScriptParam> pms = new List<GroupScriptParam>();
            var bsgps = BatchScript.GetGlobalParams();
            foreach (var bsgp in bsgps)
            {
                bsgp.ScriptParam.Name = Name +"_"+ bsgp.ScriptParam.Name;
                bsgp.ScriptParam.Description = Description+ "_" +"执行"+ bsgp.ScriptParam.Description;
            }
            pms.AddRange(bsgps);
            foreach (var fs in FunctionScripts)
            {
                var fspms = fs.GetGlobalParams();
                foreach (var pm in fspms)
                {
                    pm.ScriptParam.Name = Name + "_" + pm.ScriptParam.Name;
                    pm.ScriptParam.Description = Description + "_" + "功能" + pm.ScriptParam.Description;
                }
                pms.AddRange(fspms);
            }
            return  pms;
        }
    }

    public class Script:NotifyBase,IClone<Script>, IGetGlobalParams
    {
        private int? _id;
        public int? Id 
        {
            get { return _id; }
            set
            {
                if(value!= _id)
                {
                    _id = value;
                    OnPropertyChanged(nameof(Id));
                }
            }
        }

        private string _name;
        public string Name 
        {
            get { return _name; }
            set
            {
                if (value != _name)
                {
                    _name = value;
                    OnPropertyChanged(nameof(Name));
                }
            }
        }
        private ScriptTypeEnum _sctp;
        public ScriptTypeEnum Sctp
        {
            get { return _sctp; }
            set
            {
                if(_sctp != value)
                {
                    _sctp = value;
                    OnPropertyChanged(nameof(Sctp));
                }
            }
        }
        private string _desc;
        public string Description 
        {
            get { return _desc; }
            set
            {
                if (value != _desc)
                {
                    _desc = value;
                    OnPropertyChanged(nameof(Description));
                }
            }
        }

        
        private string _fn;
        /// <summary>
        /// 文件名，含后缀
        /// </summary>
        public string FileName
        {
            get { return _fn; }
            set
            {  
                if (_fn != value)
                {
                    _fn = value;
                    OnPropertyChanged(nameof(FileName));
                }
            }
        }

        private string _wd;
        public string WorkDir
        {
            get => _wd;
            set
            {
                if(value != _wd)
                {
                    _wd = value;
                    OnPropertyChanged(nameof(WorkDir));
                }
            }
        }

        private string _orgfp;
        /// <summary>
        /// 原始文件路径
        /// </summary>
        public string OrgFilePath
        {
            get { return _orgfp; }
            set
            {
                if (_orgfp != value)
                {
                    _orgfp = value;
                    OnPropertyChanged(nameof(OrgFilePath));
                }
            }
        }

        private string _content;
        public string Content 
        {
            get { return _content; }
            set
            {
                if(_content != value)
                {
                    _content = value;
                    OnPropertyChanged(nameof(Content));
                }
            }
        }

        private ObservableCollection<ScriptParam> scriptParams;
        /// <summary>
        /// 功能脚本参数列表
        /// </summary>
        public ObservableCollection<ScriptParam> ScriptParams 
        {
            get { return  scriptParams; }
            set
            {
                if(scriptParams != value)
                {
                    scriptParams = value;
                    OnPropertyChanged(nameof(ScriptParams));
                }
            }
        }

        public Script Clone()
        {
            var cloned =  MemberwiseClone() as Script;
            if (ScriptParams != null)
                cloned.ScriptParams = new ObservableCollection<ScriptParam>(ScriptParams);
            else
                cloned.ScriptParams = null;
            return cloned;
        }

        public List<GroupScriptParam> GetGlobalParams()
        {
            List<GroupScriptParam> pms = new List<GroupScriptParam>();
            ScriptParam sp = new ScriptParam
            {
                Name = this.Name + "_" + "ScriptFilePath",
                Description =  Description + "脚本文件路径",
                ParamType = ParamTypeEnum.StringType,
                Value = FileName,
                DefaultValue = FileName,
            };
            string grpName = GlobalParamType.ScriptFileName.GetDescription();
            pms.Add(new GroupScriptParam(sp, grpName));
            return pms;
        }

        public void MakeScriptFile()
        {
            string scriptFile = WorkDir+FileName;
            if(File.Exists(scriptFile))
            {
                Content = File.ReadAllText(scriptFile);
                foreach (var pm in ScriptParams)
                {
                    string toBeReplaced ="{[("+ pm.Id.ToString()+")]}";
                    Content=Content.Replace(toBeReplaced, pm.Value);
                }
                using (FileStream fs = new FileStream(scriptFile, FileMode.Create, FileAccess.Write))
                {
                    using (StreamWriter sw = new StreamWriter(fs))
                    {
                        sw.Write(Content);
                    }
                }
            }
        }
    }

    public enum ScriptTypeEnum
    {
        BatchScript,
        FunctionScript
    }
}
